package com.inspur.icity.bus.api.user.service;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.inspur.icity.bus.api.user.model.BusAddress;
import com.inspur.icity.bus.api.user.model.BusSite;
import com.inspur.icity.bus.api.user.repo.BusAddressDao;
import com.inspur.icity.bus.base.core.gaoderesult.*;
import com.inspur.icity.bus.base.core.service.CrudService;
import com.inspur.icity.bus.base.core.util.GaodeMapApi;
import org.apache.commons.collections.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 设置起始点、乘车方案Service
 */
@Service
public class BusAddressService extends CrudService<BusAddressDao, BusAddress, Integer> {

    @Autowired
    private BusSiteService busSiteService;

    @Autowired
    private BusRouteService busRouteService;

    private static final String GAODE_API_RESULT_STATUS = "1";

    /**
     * 获取登陆用户常用地点列表
     * @param mobile
     * @param addressType
     * @return
     */
    public List<BusAddress> getUserStartOrEndAddress(String mobile, Integer addressType,String city){
        return curdRepo.getUserStartOrEndAddress(mobile,addressType,city);
    }


    /**
     * 查询起点、终点（搜索框调用）
     * @param keywords
     * @param city
     * @return
     */
    public List<Map<String,Object>> queryAddress(String keywords,String city,String areacode){
        /*1.查询站点信息，注意经纬度小数点后个数  6位 */
        List<Map<String,Object>> userStationList = getStationInfo(keywords,areacode);

        /*2.通过高德地图关键字搜索查询地点信息*/
        InputTipsResult inputTipsResult = GaodeMapApi.search(keywords,city);
        List<TipResult> inputTipsResults = inputTipsResult != null && inputTipsResult.getTips() != null ? inputTipsResult.getTips() : new ArrayList<>();
        return this.buildResult(userStationList,inputTipsResults,city);
    }


    /**
     * 搜索地点位置信息整合 【站点信息和地点信息整合】
     * @param inspurList 站点信息
     * @param inputTipsResults 地点信息
     * @return
     */
    private List<Map<String,Object>> buildResult(List inspurList , List<TipResult> inputTipsResults, String city){
        List<Map<String,Object>> result = new ArrayList<>(10);
        int totle = 10;
        int count = 0;
        if(inspurList.size() >= totle){
            /*前10条结果返回*/
            return inspurList.subList(0,10);
        }else{
            if(inspurList.size() > 0){
                /* 把inspurList 中的数据放到 result 中*/
                result.addAll(inspurList);
            }
            for(TipResult tipResult : inputTipsResults){
                if(count++ < (totle - inspurList.size())){
                    if(tipResult.getAddress() instanceof String && tipResult.getName() instanceof String && tipResult.getLocation() instanceof String && tipResult.getDistrict() instanceof String && tipResult.getTypecode() instanceof String
                            && !"150700".equals(tipResult.getTypecode()) && !"150701".equals(tipResult.getTypecode()) && !"150702".equals(tipResult.getTypecode()) && !"150703".equals(tipResult.getTypecode())
                            && tipResult.getLocation() != null){

                        Map<String,Object> map = new HashedMap();
                        /*详细地址*/
                        map.put("xxdz",tipResult.getAddress());
                        /*名称*/
                        map.put("address",tipResult.getName());
                        map.put("lng",Double.parseDouble(tipResult.getLocation().toString().split(",")[0]));
                        map.put("lat",Double.parseDouble(tipResult.getLocation().toString().split(",")[1]));
                        /*所在区域*/
                        map.put("district",tipResult.getDistrict());
                        map.put("city",getCityByDistrict(tipResult.getDistrict().toString(), city));
                        /*0:地点；1:站点*/
                        map.put("type",0);
                        result.add(map);
                    }
                }
            }
        }
        return result;
    }

    /**
     * 判断搜索返回的地点是否是当前市
     * @param district
     * @return
     */
    private String getCityByDistrict(String district,String city) {
        int s = district.indexOf("省");
        int shi = district.indexOf("市");
        if(s != -1 && shi != -1){
            return district.substring(s+1,shi+1);
        }
        if(s == -1 && shi != -1){
            return district.substring(0,shi + 1);
        }
        return "";
    }

    /**
     * 查询站点数据
     * @param keywords 站点名称
     */
    public List<Map<String,Object>> getStationInfo(String keywords,String areacode){
        List<Map<String,Object>> result = new ArrayList<>();
        Map queryMap = new HashedMap();
        queryMap.put("keyword",keywords);
        queryMap.put("areacode",areacode);
        queryMap.put("group","GROUP BY stationName"); //站点去重
        List<BusSite> busstations = busSiteService.find(queryMap);
        for(BusSite busSite : busstations){
            Map<String,Object> map = new HashedMap();
            map.put("address",busSite.getStationName());
            map.put("lng",busSite.getLng());
            map.put("lat",busSite.getLat());
            map.put("type",1); //站点
            map.put("city",busSite.getCity());
            result.add(map);
        }
        return result;
    }


    /**
     * 查询乘车方案列表
     * @param mobile
     * @param startAddress 起始地点或站点
     * @param startLng
     * @param startLat
     * @param startType 起始点类型 0：地点 1：站点
     * @param endAddress 终点地点或站点
     * @param endLng
     * @param endLat
     * @param endType 终点类型 0：地点 1：站点
     * @param strategy
     * @param city 当前城市
     * @return
     */
    public List<Map<String,Object>> queryBusPlan(String mobile,String startAddress,double startLng,double startLat,int startType,
                                            String endAddress,double endLng,double endLat,int endType,int strategy,String city){
        /*1.保存起始点位置信息*/
        this.addList(mobile,startAddress,startLng,startLat,startType,endAddress,endLng,endLat,endType,strategy);

        /*todo 2.根据起始点位置信息查询路线信息 先根据inspur查询*/

        /*2.1 如果inspur 没有结果 调用高德地图api*/
        String origin = startLng + "," + startLat;
        String destination = endLng + "," + endLat;
        DirectionTransitResult directionTransitResult = GaodeMapApi.directionTransit(origin,destination,city,"",String.valueOf(strategy));
        if(directionTransitResult != null && GAODE_API_RESULT_STATUS.equals(directionTransitResult.getStatus())){
            RouteResult routeResult = directionTransitResult.getRoute();
            if(routeResult == null){
                return null;
            }
            List<TransitResult> transits = routeResult.getTransits();
            return buildBusRouteResult(transits,startAddress,startType,endAddress,endType);
        }
        return null;
    }


    /**
     * 批量插入地点信息
     * @param mobile
     * @param startAddress
     * @param startLng
     * @param startLat
     * @param startType
     * @param endAddress
     * @param endLng
     * @param endLat
     * @param endType
     */
    private void addList(String mobile,String startAddress,double startLng,double startLat,int startType,
                        String endAddress,double endLng,double endLat,int endType,int strategy){
        List<BusAddress> addressList = new ArrayList<>();
        /*1.逆地理查询起点终点 详细信息*/
        GaocodeRegeoResult startGeo = GaodeMapApi.geoRegeo(String.valueOf(startLng),String.valueOf(startLat));
        GaocodeRegeoResult endGeo = GaodeMapApi.geoRegeo(String.valueOf(endLng),String.valueOf(endLat));

        //起点位置封装
        BusAddress startBusAddress = buildAddress(mobile,startLng,startLat,startAddress,0,startType,strategy,startGeo);
        addressList.add(startBusAddress);

        //终点位置封装
        BusAddress endBusAddress = buildAddress(mobile,endLng,endLat,endAddress,1,endType,strategy,endGeo);
        addressList.add(endBusAddress);

        /*4.起点、终点位置信息保存*/
        curdRepo.batchAdd(addressList);

    }

    /**
     * 起始点位置封装
     * @param mobile
     * @param lng
     * @param lat
     * @param address
     * @param addressType
     * @param type
     * @param strategy
     * @param geo
     * @return
     */
    private BusAddress buildAddress(String mobile, double lng, double lat, String address, int addressType, int type, int strategy,GaocodeRegeoResult geo) {
        BusAddress busAddress = new BusAddress();
        busAddress.setMobile(mobile);
        busAddress.setLng(lng);
        busAddress.setLat(lat);
        busAddress.setAddress(address);
        busAddress.setAddressType(addressType); //起点or终点
        busAddress.setType(type);
        busAddress.setStrategy(strategy);
        if(geo != null && geo.getRegeocode() != null && geo.getRegeocode().getAddressComponent() != null){
            if(geo.getRegeocode().getAddressComponent().getDistrict() instanceof String){
                busAddress.setDistrict(geo.getRegeocode().getAddressComponent().getDistrict().toString());
            }
            if(geo.getRegeocode().getAddressComponent().getCity() instanceof String){
                busAddress.setCity(geo.getRegeocode().getAddressComponent().getCity().toString());
            }
            if(geo.getRegeocode().getAddressComponent().getProvince() instanceof String){
                busAddress.setProvince(geo.getRegeocode().getAddressComponent().getProvince().toString());
            }

        }
        return busAddress;
    }

    /**
     * 构建高德公交路径规划结果
     * @param transitResults
     * @return
     */
    public List<Map<String,Object>> buildBusRouteResult(List<TransitResult> transitResults,String startAddress,int strAddressType,String endAddress,int endAddressType){
        List<Map<String,Object>> result = new ArrayList<>();

        if(transitResults == null){
            return result;
        }
        int count = 1;
        for(TransitResult transitResult : transitResults){
            Map<String,Object> planMap = new HashedMap();
            planMap.put("name","方案"+transformNum(count++));
            /*方案详情*/
            List<Map<String,Object>> planList = new ArrayList<>();
            /*方案总览*/
            List<Map<String,Object>> overviewList = new ArrayList<>();

             /*设置起点信息*/
            Map startAddressMap = new HashedMap();
            startAddressMap.put("type",1);
            startAddressMap.put("name","起点");
            startAddressMap.put("content",startAddress);
            planList.add(startAddressMap);

            List<Map<String,Object>> segments = transitResult.getSegments();
            if(segments != null){
                for(int i = 0 ; i < segments.size() ; i++){

                    /*起点为站点，首次步行方案忽略，或终点为站点，最后一次步行方案忽略*/
                    boolean flag = (i == 0 && strAddressType == 1)||( i == (segments.size()-1) && endAddressType == 1);

                    Map segment = segments.get(i);
                    /*获取每种方案 步行规划行程*/
                    if(!flag){
                        List<Map<String,Object>> walkingList = buildOneWalking(segment);
                        if(walkingList != null && walkingList.size() > 0){
                            planList.addAll(walkingList);
                        }
                    }

                    boolean departureStopShow = showStartSite(planList,(i == 0 && strAddressType == 1));
                    boolean arrivalStopShow = !( i == (segments.size()-1) && endAddressType == 1);

                    /*获取每种方案 公交规划行程*/
                    List<Map<String,Object>> busList = buildOneBus(segment,departureStopShow,arrivalStopShow);
                    if(busList != null && busList.size() > 0){
                        planList.addAll(busList);
                    }
                    /*获取公交规划行程  总览详情*/
                    boolean changeSite = i == 0 ? false : true;
                    List<Map<String,Object>> busOverviewList = buildOverviewBus(segment,changeSite);
                    if(busOverviewList != null && busOverviewList.size() > 0){
                        overviewList.addAll(busOverviewList);
                    }

                }
                 /*设置终点信息*/
                Map endAddressMap = new HashedMap();
                endAddressMap.put("type",2);
                endAddressMap.put("name","终点");
                endAddressMap.put("content",endAddress);
                planList.add(endAddressMap);

                planMap.put("detail",planList);
                planMap.put("trainsit",overviewList);
            }
            result.add(planMap);
        }

        return result;
    }


    /**
     *  获取公交方案详情 中 是否显示到达公交起点
     *  到达站点起点   -->  到达站点终点  过程 是否显示达到站点起点
     */
    public boolean showStartSite(List<Map<String,Object>> planList,boolean isStartSite){
        boolean flag = true;
        if(planList != null && planList.size() > 1){
            /*有路线规划,并且为到达公交终点 此时不显示到达公交站点起点*/
            Map<String,Object> map = planList.get(planList.size()-1);
            if(Integer.parseInt(map.get("type").toString()) == 7){
                    return false;
            }
        }else{
            /*起点为站点 此时不显示到达公交站点起点*/
            if(isStartSite){
                return false;
            }
        }
        return flag;
    }

    /**
     * 获取公交线路概览
     * @param segment
     * @return
     */
    public List<Map<String,Object>> buildOverviewBus(Map<String,Object> segment,boolean changeSite) {
        List<Map<String,Object>> result = new ArrayList<>();
        if(segment == null){
            return null;
        }

        /*1.获取公交详情 type 8:乘车站 9:换乘站 10:乘坐 11:换乘 */
        Map<String,Object> busMap = (Map<String,Object>)segment.get("bus");
        List<Map<String,Object>> list = (List<Map<String,Object>>)busMap.get("buslines");
        Gson gson = new Gson();
        String busjson = gson.toJson(list);
        List<BuslineResult> buslineResults = gson.fromJson(busjson,new TypeToken<List<BuslineResult>>() {}.getType());

        if(buslineResults != null && buslineResults.size() > 0){
            BuslineResult buslineResult = buslineResults.get(0);
            Map<String,Object> map = new HashedMap();
            map.put("type",!changeSite ? 8 : 9);
            map.put("name",!changeSite ? "乘车站" : "换乘站");
            map.put("content",buslineResult.getDepartureStop().getName() + "站");
            result.add(map);
            Map<String,Object> lineMap = new HashedMap();
            lineMap.put("type",!changeSite  ? 10 : 11);
            lineMap.put("name",!changeSite  ? "乘坐" : "换乘");
            lineMap.put("content",getLineNameFromName(buslineResult.getName()));
            result.add(lineMap);
        }
        return result;
    }

    /**
     * 获取步行方案详情
     * @param segment
     * @return
     */
    public List<Map<String,Object>> buildOneWalking(Map<String,Object> segment){
        List<Map<String,Object>> result = new ArrayList<>();
        if(segment == null){
            return null;
        }

        /*1.获取步行 type 1:起点 2:终点 3:步行 4:乘坐 5:途径 6:到达公交起点 7:到达公交终点*/
        if(segment.get("walking") instanceof  Map){
            Map<String,Object> walkingMap = (Map<String,Object>)segment.get("walking");
            if(walkingMap != null && walkingMap.size() > 0 && walkingMap.get("distance") != null){
                Map<String,Object> map = new HashedMap();
                map.put("type",3);
                map.put("name","步行");
                map.put("content",getWalkingDistanceDescription(walkingMap.get("distance").toString()));
                result.add(map);
            }
        }
        return result;
    }

    /**
     * 获取公交方案详情
     * @param segment
     * @return
     */
    public List<Map<String,Object>> buildOneBus(Map<String,Object> segment,boolean departureStopShow,boolean arrivalStopShow){
        List<Map<String,Object>> result = new ArrayList<>();
        if(segment == null){
            return null;
        }

        /*1.获取公交详情 type 1:起点 2:终点 3:步行 4:乘坐 5:途径 6:到达公交起点 7:到达公交终点*/
        Map<String,Object> busMap = (Map<String,Object>)segment.get("bus");
        List<Map<String,Object>> list = (List<Map<String,Object>>)busMap.get("buslines");
        Gson gson = new Gson();
        String busjson = gson.toJson(list);
        List<BuslineResult> buslineResults = gson.fromJson(busjson,new TypeToken<List<BuslineResult>>() {}.getType());

        if(buslineResults != null && buslineResults.size() > 0){
            BuslineResult buslineResult = buslineResults.get(0);
            if(departureStopShow){
                Map<String,Object> map = new HashedMap();
                map.put("type",6);
                map.put("name","到达");
                map.put("content",buslineResult.getDepartureStop().getName() + "站");
                result.add(map);
            }
            Map<String,Object> lineMap = new HashedMap();
            lineMap.put("type",4);
            lineMap.put("name","乘坐");
            lineMap.put("content",getLineNameFromName(buslineResult.getName()) + " 方向：" + getDriectionFromName(buslineResult.getName()));
            String lineName = getLineNameFromName(buslineResult.getName());
            lineName = lineName.indexOf("/") > 0 ? lineName.substring(0,lineName.indexOf("/")) : lineName; //获取的第一个线路名称，例如：116路/K116路，现在获取的是116路
            lineMap.put("line",lineName);
            lineMap.put("direction",getDriectionFromName(buslineResult.getName()));
            result.add(lineMap);
            Map<String,Object> siteNumMap = new HashedMap();
            siteNumMap.put("type",5);
            siteNumMap.put("name","途径");
            siteNumMap.put("content",buslineResult.getViaNum() + "个站点 （" + getWalkingDistanceDescription(buslineResult.getDistance()) +
                    "  " + getTimeLongDescription(buslineResult.getDuration()) +"）");
            result.add(siteNumMap);
            if(arrivalStopShow){
                Map<String,Object> arrialMap = new HashedMap();
                arrialMap.put("type",7);
                arrialMap.put("name","到达");
                arrialMap.put("content",buslineResult.getArrivalStop().getName() + "站");
                result.add(arrialMap);
            }
        }
        return result;
    }

    /**
     * 获取距离
     * @param distance
     * @return
     */
    public static String getWalkingDistanceDescription(String distance){
        String result = "101米";
        if (StringUtils.isEmpty(distance)){
            return result;
        }
        int dis = Integer.parseInt(distance);
        if(dis/1000 >= 1){
            if(dis%1000 < 100){
                result = dis/1000 + "公里";
            }else{
                DecimalFormat df=new DecimalFormat("0.0");
                result = df.format((float)dis/1000) + "公里";
            }
        }else{
            result = distance + "米";
        }
        return result;
    }

    /**
     * 获取时长
     * @param duration
     * @return
     */
    public static String getTimeLongDescription(String duration){
        String result = "10分钟";
        if(StringUtils.isEmpty(duration)){
            return result;
        }
        int sdu = Integer.parseInt(duration);
        if(sdu/60 >= 60){
            result = sdu/(60*60) + "小时";
        }else if( sdu/60 < 60 && sdu/60 > 0){
            result = sdu/60 + "分钟";
        }else{
            result = "1分钟";
        }

        return result;
    }

    /**
     * 根据名称获取方向 高德地图名称 40路/K40路(凤凰路陈家路--全运媒体村)
     * @param name
     */
    public static String getDriectionFromName(String name){
        String result = "";
        String patternString = "--[\\u4e00-\\u9fa5]+\\)";
        Pattern pattern = Pattern.compile(patternString);
        Matcher matcher = pattern.matcher(name);
        while(matcher.find()) {
            result = name.substring((matcher.start()+2),(matcher.end()-1));
        }
        return result;
    }

    /**
     * 根据名称获取线路 高德地图名称 40路/K40路(凤凰路陈家路--全运媒体村)
     * @param name
     */
    public static String getLineNameFromName(String name){
        String result = "";
        String patternString = "\\(";
        Pattern pattern = Pattern.compile(patternString);
        Matcher matcher = pattern.matcher(name);
        while(matcher.find()) {
            result = name.substring(0,matcher.start());
        }
        return result;
    }

    /**
     * 数据转换
     * @param num
     * @return
     */
    public static String transformNum(int num){
        String[] numStr = {"零","一","二","三","四","五","六","七","八","九"};
        return numStr[num];
    }


    /**
     * 方案详情，判断方案中路线和站点在库中是否存在
     * @param detail
     * @param areacode
     * @return
     */
    public List<Map<String,Object>> queryBusPlanDetail(List<Map<String, Object>> detail, String areacode) {
        for (int i = 0; i<detail.size(); i++){
            if((i == 0)|| (i == detail.size()-1)){ //过滤首尾
                continue;
            }
            Map<String,Object> map = detail.get(i);
            Integer type = map.get("type") != null?(Integer)map.get("type"):0;
            if(type == 6 || type == 7){ //站点
                String name = map.get("content") != null?map.get("content").toString():"";
                name = name.replace("站","");
                int count = busSiteService.getSiteCount(name,areacode);
                if(count>0){
                    map.put("isExist",1); //库中存在
                }
            }
            if(type == 4){ //线路
                String name = map.get("line") != null?map.get("line").toString():"";
                String direction = map.get("direction") != null ? map.get("direction").toString()+"方向" : "";
                int count = busRouteService.getRouteCount(name,direction,areacode);
                if(count>0){
                    map.put("isExist",1);
                }
            }
        }
        return detail;
    }

}